# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s

...
---
name:            or_combine_sext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; or (sext X), (sext Y) --> sext (or X, Y)
    ;
    ; CHECK-LABEL: name: or_combine_sext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_SEXT [[OR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_SEXT %x(s32)
    %hand2:_(s64) = G_SEXT %y(s32)
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_zext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; or (zext X), (zext Y) --> zext (or X, Y)
    ;
    ; CHECK-LABEL: name: or_combine_zext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ZEXT [[OR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ZEXT %x(s32)
    %hand2:_(s64) = G_ZEXT %y(s32)
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_anyext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; or (anyext X), (anyext Y) --> anyext (or X, Y)
    ;
    ; CHECK-LABEL: name: or_combine_anyext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ANYEXT [[OR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ANYEXT %x(s32)
    %hand2:_(s64) = G_ANYEXT %y(s32)
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_sext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; and (sext X), (sext Y) --> sext (and X, Y)
    ;
    ; CHECK-LABEL: name: and_combine_sext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_SEXT [[AND]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_SEXT %x(s32)
    %hand2:_(s64) = G_SEXT %y(s32)
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_zext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; and (zext X), (zext Y) --> zext (and X, Y)
    ;
    ; CHECK-LABEL: name: and_combine_zext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_ZEXT [[AND]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ZEXT %x(s32)
    %hand2:_(s64) = G_ZEXT %y(s32)
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_anyext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; and (anyext X), (anyext Y) --> anyext (and X, Y)
    ;
    ; CHECK-LABEL: name: and_combine_anyext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_ANYEXT [[AND]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ANYEXT %x(s32)
    %hand2:_(s64) = G_ANYEXT %y(s32)
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_sext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; xor (sext X), (sext Y) --> sext (xor X, Y)
    ;
    ; CHECK-LABEL: name: xor_combine_sext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_SEXT [[XOR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_SEXT %x(s32)
    %hand2:_(s64) = G_SEXT %y(s32)
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_zext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; xor (zext X), (zext Y) --> zext (xor X, Y)
    ;
    ; CHECK-LABEL: name: xor_combine_zext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ZEXT [[XOR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ZEXT %x(s32)
    %hand2:_(s64) = G_ZEXT %y(s32)
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_anyext
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; xor (anyext X), (anyext Y) --> anyext (xor X, Y)
    ;
    ; CHECK-LABEL: name: xor_combine_anyext
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ANYEXT [[XOR]](s32)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_ANYEXT %x(s32)
    %hand2:_(s64) = G_ANYEXT %y(s32)
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            dont_combine_different_types
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; When %x and %y don't have the same type, don't perform the combine.
    ;
    ; CHECK-LABEL: name: dont_combine_different_types
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %hand1:_(s32) = COPY $w1
    ; CHECK: %y:_(s16) = G_TRUNC %hand1(s32)
    ; CHECK: %hand2:_(s64) = G_SEXT %x(s32)
    ; CHECK: %logic_op:_(s64) = G_SEXT %y(s16)
    ; CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR %hand2, %logic_op
    ; CHECK: $x0 = COPY [[OR]](s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %hand1:_(s32) = COPY $w1
    %y:_(s16) = G_TRUNC %hand1(s32)
    %hand2:_(s64) = G_SEXT %x(s32)
    %logic_op:_(s64) = G_SEXT %y(s16)
    %5:_(s64) = G_OR %hand2, %logic_op
    $x0 = COPY %5(s64)
    RET_ReallyLR implicit $x0

...
---
name:            illegal_ty
tracksRegLiveness: true
legalized: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; Pre-legalization, it's okay to produce illegal types.
    ;
    ; CHECK-LABEL: name: illegal_ty
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x_wide:_(s32) = COPY $w0
    ; CHECK: %y_wide:_(s32) = COPY $w1
    ; CHECK: %x:_(s1) = G_TRUNC %x_wide(s32)
    ; CHECK: %y:_(s1) = G_TRUNC %y_wide(s32)
    ; CHECK: [[OR:%[0-9]+]]:_(s1) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_SEXT [[OR]](s1)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x_wide:_(s32) = COPY $w0
    %y_wide:_(s32) = COPY $w1
    %x:_(s1) = G_TRUNC %x_wide
    %y:_(s1) = G_TRUNC %y_wide
    %hand1:_(s64) = G_SEXT %x(s1)
    %hand2:_(s64) = G_SEXT %y(s1)
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_and
tracksRegLiveness: true
body:             |
  bb.0:
    ; or (and x, z), (and y, z) --> and (or x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: or_combine_and
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_AND [[OR]], %z
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_AND %x(s64), %z
    %hand2:_(s64) = G_AND %y(s64), %z
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_ashr
tracksRegLiveness: true
body:             |
  bb.0:
    ; or (ashr x, z), (ashr y, z) --> ashr (or x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: or_combine_ashr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ASHR [[OR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_ASHR %x(s64), %z
    %hand2:_(s64) = G_ASHR %y(s64), %z
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_lshr
tracksRegLiveness: true
body:             |
  bb.0:
    ; or (lshr x, z), (lshr y, z) --> lshr (or x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: or_combine_lshr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_LSHR [[OR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_LSHR %x(s64), %z
    %hand2:_(s64) = G_LSHR %y(s64), %z
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            or_combine_shl
tracksRegLiveness: true
body:             |
  bb.0:
    ; or (shl x, z), (shl y, z) --> shl (or x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: or_combine_shl
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y
    ; CHECK: %logic_op:_(s64) = G_SHL [[OR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_SHL %x(s64), %z
    %hand2:_(s64) = G_SHL %y(s64), %z
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_and
tracksRegLiveness: true
body:             |
  bb.0:
    ; xor (and x, z), (and y, z) --> and (xor x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: xor_combine_and
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_AND [[XOR]], %z
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_AND %x(s64), %z
    %hand2:_(s64) = G_AND %y(s64), %z
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_ashr
tracksRegLiveness: true
body:             |
  bb.0:
    ; xor (ashr x, z), (ashr y, z) --> ashr (xor x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: xor_combine_ashr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_ASHR [[XOR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_ASHR %x(s64), %z
    %hand2:_(s64) = G_ASHR %y(s64), %z
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_lshr
tracksRegLiveness: true
body:             |
  bb.0:
    ; xor (lshr x, z), (lshr y, z) --> lshr (xor x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: xor_combine_lshr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_LSHR [[XOR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_LSHR %x(s64), %z
    %hand2:_(s64) = G_LSHR %y(s64), %z
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            xor_combine_shl
tracksRegLiveness: true
body:             |
  bb.0:
    ; xor (shl x, z), (shl y, z) --> shl (xor x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: xor_combine_shl
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y
    ; CHECK: %logic_op:_(s64) = G_SHL [[XOR]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_SHL %x(s64), %z
    %hand2:_(s64) = G_SHL %y(s64), %z
    %logic_op:_(s64) = G_XOR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_and
tracksRegLiveness: true
body:             |
  bb.0:
    ; and (and x, z), (and y, z) --> and (and x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: and_combine_and
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_AND [[AND]], %z
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_AND %x(s64), %z
    %hand2:_(s64) = G_AND %y(s64), %z
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_ashr
tracksRegLiveness: true
body:             |
  bb.0:
    ; and (ashr x, z), (ashr y, z) --> ashr (and x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: and_combine_ashr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_ASHR [[AND]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_ASHR %x(s64), %z
    %hand2:_(s64) = G_ASHR %y(s64), %z
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_lshr
tracksRegLiveness: true
body:             |
  bb.0:
    ; and (lshr x, z), (lshr y, z) --> lshr (and x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: and_combine_lshr
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_LSHR [[AND]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_LSHR %x(s64), %z
    %hand2:_(s64) = G_LSHR %y(s64), %z
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            and_combine_shl
tracksRegLiveness: true
body:             |
  bb.0:
    ; and (shl x, z), (shl y, z) --> shl (and x, y), z
    ;
    liveins: $x0, $x1, $x2
    ; CHECK-LABEL: name: and_combine_shl
    ; CHECK: liveins: $x0, $x1, $x2
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z:_(s64) = COPY $x2
    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y
    ; CHECK: %logic_op:_(s64) = G_SHL [[AND]], %z(s64)
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z:_(s64) = COPY $x2
    %hand1:_(s64) = G_SHL %x(s64), %z
    %hand2:_(s64) = G_SHL %y(s64), %z
    %logic_op:_(s64) = G_AND %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:            dont_combine_different_defs_on_binop
tracksRegLiveness: true
body:             |
  bb.0:
    ; z1 != z2, so don't combine.
    ;
    liveins: $x0, $x1, $x2, $x3
    ; CHECK-LABEL: name: dont_combine_different_defs_on_binop
    ; CHECK: liveins: $x0, $x1, $x2, $x3
    ; CHECK: %x:_(s64) = COPY $x0
    ; CHECK: %y:_(s64) = COPY $x1
    ; CHECK: %z1:_(s64) = COPY $x2
    ; CHECK: %z2:_(s64) = COPY $x3
    ; CHECK: %hand1:_(s64) = G_AND %x, %z1
    ; CHECK: %hand2:_(s64) = G_AND %y, %z2
    ; CHECK: %logic_op:_(s64) = G_OR %hand1, %hand2
    ; CHECK: $x0 = COPY %logic_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s64) = COPY $x0
    %y:_(s64) = COPY $x1
    %z1:_(s64) = COPY $x2
    %z2:_(s64) = COPY $x3
    %hand1:_(s64) = G_AND %x(s64), %z1
    %hand2:_(s64) = G_AND %y(s64), %z2
    %logic_op:_(s64) = G_OR %hand1, %hand2
    $x0 = COPY %logic_op(s64)
    RET_ReallyLR implicit $x0

...
---
name: dont_combine_more_than_one_use
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; The LHS register is used more than once. Don't combine.
    ;
    ; CHECK-LABEL: name: dont_combine_more_than_one_use
    ; CHECK: liveins: $w0, $w1
    ; CHECK: %x:_(s32) = COPY $w0
    ; CHECK: %y:_(s32) = COPY $w1
    ; CHECK: %hand1:_(s64) = G_SEXT %x(s32)
    ; CHECK: %hand2:_(s64) = G_SEXT %y(s32)
    ; CHECK: %logic_op:_(s64) = G_OR %hand1, %hand2
    ; CHECK: %other_op:_(s64) = G_ADD %hand1, %logic_op
    ; CHECK: $x0 = COPY %other_op(s64)
    ; CHECK: RET_ReallyLR implicit $x0
    %x:_(s32) = COPY $w0
    %y:_(s32) = COPY $w1
    %hand1:_(s64) = G_SEXT %x(s32)
    %hand2:_(s64) = G_SEXT %y(s32)
    %logic_op:_(s64) = G_OR %hand1, %hand2
    %other_op:_(s64) = G_ADD %hand1, %logic_op
    $x0 = COPY %other_op(s64)
    RET_ReallyLR implicit $x0

...
---
name:           combine_vector
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $d0, $d1
    ; Show that we can combine vector types.
    ;
    ; CHECK-LABEL: name: combine_vector
    ; CHECK: liveins: $d0, $d1
    ; CHECK: %x:_(<2 x s32>) = COPY $d0
    ; CHECK: %y:_(<2 x s32>) = COPY $d1
    ; CHECK: [[OR:%[0-9]+]]:_(<2 x s32>) = G_OR %x, %y
    ; CHECK: %logic_op:_(<2 x s64>) = G_SEXT [[OR]](<2 x s32>)
    ; CHECK: $q0 = COPY %logic_op(<2 x s64>)
    ; CHECK: RET_ReallyLR implicit $q0
    %x:_(<2 x s32>) = COPY $d0
    %y:_(<2 x s32>) = COPY $d1
    %hand1:_(<2 x s64>) = G_SEXT %x(<2 x s32>)
    %hand2:_(<2 x s64>) = G_SEXT %y(<2 x s32>)
    %logic_op:_(<2 x s64>) = G_OR %hand1, %hand2
    $q0 = COPY %logic_op(<2 x s64>)
    RET_ReallyLR implicit $q0
